package com.tabjin.rfidsocket.service.access.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.tabjin.rfidsocket.common.enums.UserStatusEnum;
import com.tabjin.rfidsocket.common.org.n3r.idworker.Sid;
import com.tabjin.rfidsocket.common.utils.BeanValidator;
import com.tabjin.rfidsocket.common.utils.PagedGridResult;
import com.tabjin.rfidsocket.exception.ParamException;
import com.tabjin.rfidsocket.mapper.mapper.ArchBuildingCustomMapper;
import com.tabjin.rfidsocket.mapper.mapper.ArchBuildingMapper;
import com.tabjin.rfidsocket.mapper.mapper.ArchProjectBuildingUserMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysUserMapper;
import com.tabjin.rfidsocket.pojo.ArchBuilding;
import com.tabjin.rfidsocket.pojo.ArchProjectBuildingUser;
import com.tabjin.rfidsocket.pojo.SysUser;
import com.tabjin.rfidsocket.pojo.bo.access.ArchBuildingBO;
import com.tabjin.rfidsocket.pojo.vo.access.ArchBuildingVO;
import com.tabjin.rfidsocket.service.access.ArchBuildingService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author tabjin
 * create at 2021/1/14 15:23
 * @program rfid_socket
 * @description
 */
@Service
public class ArchBuildingServiceImpl implements ArchBuildingService {

    static final Logger logger = LoggerFactory.getLogger(ArchBuildingServiceImpl.class);

    private final ArchBuildingMapper archBuildingMapper;
    private final ArchBuildingCustomMapper archBuildingCustomMapper;
    private final ArchProjectBuildingUserMapper archProjectBuildingUserMapper;
    private final SysUserMapper sysUserMapper;
    private final Sid sid;

    public ArchBuildingServiceImpl(ArchBuildingMapper archBuildingMapper, ArchBuildingCustomMapper archBuildingCustomMapper, ArchProjectBuildingUserMapper archProjectBuildingUserMapper, SysUserMapper sysUserMapper, Sid sid) {
        this.archBuildingMapper = archBuildingMapper;
        this.archBuildingCustomMapper = archBuildingCustomMapper;
        this.archProjectBuildingUserMapper = archProjectBuildingUserMapper;
        this.sysUserMapper = sysUserMapper;
        this.sid = sid;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void add(ArchBuildingBO archBuildingBO) {
        BeanValidator.check(archBuildingBO);
        // 查重
        if (checkExist(archBuildingBO.getProjectId(), archBuildingBO.getProjectName(), archBuildingBO.getName())) {
            logger.error("该项目下待新增的楼栋存在同名楼栋，请换一个楼栋名称");
            throw new ParamException("该项目下待新增的楼栋存在同名楼栋，请换一个楼栋名称");
        }

        ArchBuilding archBuilding = ArchBuilding.builder()
//                .id(sid.nextShort())
                .projectId(archBuildingBO.getProjectId())
                .province(archBuildingBO.getProvince())
                .city(archBuildingBO.getCity())
                .projectName(archBuildingBO.getProjectName())
                .unitCode(archBuildingBO.getUnitCode())
                .name(archBuildingBO.getName())
                .totalFloor(archBuildingBO.getTotalFloor())
                .constructionAge(archBuildingBO.getConstructionAge())
                .propertyRight(archBuildingBO.getPropertyRight())
                .isElevator(archBuildingBO.getIsElevator())
                .createTime(new Date())
                .updateTime(new Date())
                .operator("张进")
                .operatorIp("127.0.0.1")
                .build();

        archBuildingMapper.insertSelective(archBuilding);
    }

    /**
     * 删除楼栋
     *
     * @param buildingId
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void delete(Integer buildingId) {
        ArchBuilding archBuilding = archBuildingMapper.selectByPrimaryKey(buildingId);
        Preconditions.checkNotNull(archBuilding, "待删除的楼栋为空");
        archBuildingMapper.deleteByPrimaryKey(buildingId);
    }

    @Override
    public ArchBuildingVO update(ArchBuildingBO archBuildingBO) {
        BeanValidator.check(archBuildingBO);
        // 查重
        if (checkExist(archBuildingBO.getProjectId(), archBuildingBO.getProjectName(), archBuildingBO.getName())) {
            logger.error("该项目下待更新的楼栋存在同名楼栋，请换一个楼栋名称");
            throw new ParamException("该项目下待更新的楼栋存在同名楼栋，请换一个楼栋名称");
        }

        ArchBuilding after = ArchBuilding.builder()
                .id(archBuildingBO.getId())
                .projectId(archBuildingBO.getProjectId())
                .province(archBuildingBO.getProvince())
                .city(archBuildingBO.getCity())
                .projectName(archBuildingBO.getProjectName())
                .unitCode(archBuildingBO.getUnitCode())
                .name(archBuildingBO.getName())
                .totalFloor(archBuildingBO.getTotalFloor())
                .constructionAge(archBuildingBO.getConstructionAge())
                .propertyRight(archBuildingBO.getPropertyRight())
                .isElevator(archBuildingBO.getIsElevator())
                .updateTime(new Date())
                .operator("张进")
                .operatorIp("127.0.0.1")
                .build();

        archBuildingMapper.updateByPrimaryKey(after);

        ArchBuildingVO vo = new ArchBuildingVO();
        BeanUtils.copyProperties(after, vo);
        return vo;
    }

    /**
     * 获取所有楼栋
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult getAll(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);

        List<ArchBuilding> archBuildingList = archBuildingMapper.selectAll();
        List<ArchBuildingVO> archBuildingVOList = archBuildingList.stream().map(item -> {
            ArchBuildingVO vo = new ArchBuildingVO();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList());

        return setPagesGrid(archBuildingVOList, page);
    }

    /**
     * 获取单个楼栋
     *
     * @param buildingId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Optional<ArchBuilding> getItem(Integer buildingId) {
        Preconditions.checkNotNull(buildingId, "楼栋id为空");
        return Optional.ofNullable(archBuildingMapper.selectByPrimaryKey(buildingId));

    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult getBuildingsByProjectId(Integer projectId, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);

        Preconditions.checkNotNull(projectId, "项目id为空");
        Example example = new Example(ArchBuilding.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("projectId", projectId);
        List<ArchBuilding> archBuildingList = archBuildingMapper.selectByExample(example);
        return setPagesGrid(archBuildingList, page);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ArchBuilding> getBuildingsByProjectId(Integer projectId) {
        Preconditions.checkNotNull(projectId, "项目id为空");
        Example example = new Example(ArchBuilding.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("projectId", projectId);
        return archBuildingMapper.selectByExample(example);
    }

    /**
     * 获取楼栋下用户
     *
     * @param buildingId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<SysUser> getBuildingUsers(Integer buildingId) {
        Preconditions.checkNotNull(buildingId, "楼栋id空");
        Example example = new Example(ArchProjectBuildingUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("buildingId", buildingId);
        List<ArchProjectBuildingUser> archProjectBuildingUsers = archProjectBuildingUserMapper.selectByExample(example);
        archProjectBuildingUsers = archProjectBuildingUsers.stream().filter(archProjectBuildingUser -> archProjectBuildingUser.getStatus() == UserStatusEnum.NORMAL.ordinal()).collect(Collectors.toList());
        List<SysUser> userList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(archProjectBuildingUsers)) {
            List<Integer> userIdList = archProjectBuildingUsers.stream().map(archProjectBuildingUser -> {
                return archProjectBuildingUser.getUserId();
            }).collect(Collectors.toList());
            userList = sysUserMapper.getUserByUserIdList(userIdList);
            userList = userList.stream().filter(sysUser -> sysUser.getStatus() == UserStatusEnum.NORMAL.ordinal()).collect(Collectors.toList());
        }
        return userList;
    }

    /**
     * 根据楼栋 id 查询楼栋
     *
     * @param buildingId 楼栋 id
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public ArchBuildingVO searchItemByBuildingId(Integer buildingId) {
        Preconditions.checkNotNull(buildingId, "楼栋id为空");
        ArchBuilding archBuilding = archBuildingMapper.selectByPrimaryKey(buildingId);
        ArchBuildingVO vo = new ArchBuildingVO();
        BeanUtils.copyProperties(archBuilding, vo);
        return vo;
    }

    /**
     * @param projectId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ArchBuildingVO> searchItemsByProjectId(Integer projectId) {
        Example example = new Example(ArchBuilding.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("projectId", projectId);
        List<ArchBuilding> archBuildingList = archBuildingMapper.selectByExample(example);
        List<ArchBuildingVO> voList = archBuildingList.stream().map(item -> {
            ArchBuildingVO vo = new ArchBuildingVO();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList());
        return voList;
    }

    /**
     * 根据项目或用户获取楼栋
     *
     * @param userId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Optional<List<ArchBuildingVO>> searchItemsByProjectIdAndUserId(Integer projectId, Integer userId) {
        Preconditions.checkNotNull(userId, "用户id空");
        Example example = new Example(ArchProjectBuildingUser.class);
        Example.Criteria criteria = example.createCriteria();
        if (projectId != null) {
            criteria.andEqualTo("projectId", projectId);
        }
        criteria.andEqualTo("userId", userId);
        Optional<List<ArchProjectBuildingUser>> archProjectBuildingUserOptional = Optional.ofNullable(archProjectBuildingUserMapper.selectByExample(example));
        List<ArchProjectBuildingUser> archProjectBuildingUserList = archProjectBuildingUserOptional.orElseThrow(() -> new ParamException("项目楼栋用户空"));
        // 楼栋id列表
        List<Integer> buildingIdList = archProjectBuildingUserList.stream().map((item) -> {
            return item.getBuildingId();
        }).collect(Collectors.toList());
        // 根据楼栋列表查询
        return Optional.ofNullable(archBuildingCustomMapper.searchItemByBuildingIdList(buildingIdList));
    }

    /**
     * 楼栋列表
     *
     * @param buildingIdList 楼栋 id 列表
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ArchBuildingVO> searchItemByBuildingIdList(List<Integer> buildingIdList) {
        List<ArchBuildingVO> archBuildingVOList = archBuildingCustomMapper.searchItemByBuildingIdList(buildingIdList);
        return archBuildingVOList;
    }

    /**
     * 数据查重
     *
     * @param projectId    项目id
     * @param projectName  项目名称
     * @param buildingName 楼栋名称
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    boolean checkExist(Integer projectId, String projectName, String buildingName) {
        Example example = new Example(ArchBuilding.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("projectId", projectId);
        criteria.andEqualTo("projectName", projectName);
        criteria.andEqualTo("name", buildingName);
        return archBuildingMapper.selectCountByExample(example) > 0;
    }

    /**
     * 获取产权性质
     *
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<String> getPropertyRight() {

        return null;
    }

    /**
     * 封装分页助手
     *
     * @param list
     * @param page
     * @return
     */
    private PagedGridResult setPagesGrid(List<?> list, Integer page) {
        PageInfo pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;
    }
}
